package com.cskaoyan.javase.string._3intern;

/**
 * public native String intern();
 * intern方法的作用是在Java程序的运行期间
 * 主动的去将一个String对象的地址存入字符串常量池
 * 使得这个String对象成为一个拘留字符串对象，再返回这个拘留字符串对象的地址（引用）。
 *
 * 由于它是一个本地方法，通过查看JDK文档，我们知道它的执行逻辑是这样的：
 *      首先会判断一下该字符串内容的String对象是否已经将地址存入字符串常量池了（就是判断是否已有相同内容的拘留字符串）
 *      这时就有了两种情况：
 *      1.如果相同内容的拘留字符串已经存在，那么该方法直接返回拘留字符串对象（的引用）。
 *      2.如果相同内容的拘留字符串不存在，那么此时调用方法的String对象肯定是一个非拘留字符串，对象直接存储在堆上,引用就没有存储在字符串常量池中。
 *      那么就直接将该对象的地址存入字符串常量池就可以了。
 *      这时调用intern方法的String对象就从非拘留字符串对象变成了一个拘留字符串对象。
 *      将该对象的地址存储进字符串常量池后,该方法会返回这个字符串对象的地址.
 *
 * @since 11:02
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // h1和h2两个字符串对象都是拘留字符串
        // 代码拼接得到的"h1h2"也就是str对象还不是拘留字符串
        String str = new String("h1") + new String("h2");

        // "h1h2"在该行代码执行时将地址存入字符串常量池,成为一个拘留字符串,返回值是str对象的地址
        // intern方法不会创建对象,只会将对象地址存入字符串常量池,并且返回这个地址
        String str2 = str.intern();


        // 代码执行到这里时,"h1h2"已经成为了拘留字符串,所以再次使用常量赋值时,要共享这个拘留字符串,也就是共享str引用指向的对象
        String str3 = "h1h2";

        // true
        System.out.println(str == str2);
        // true
        System.out.println(str == str3);
        // true
        System.out.println(str2 == str3);
    }
}
